package com.macllvm.whale.net;

import android.util.Log;

import java.lang.InterruptedException;
import java.lang.System;
import java.nio.channels.SocketChannel;
import java.nio.channels.FileChannel;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.io.RandomAccessFile;
import java.io.File;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import com.macllvm.whale.protocol.ProtocolController;
import com.macllvm.whale.entity.Transfer;
import com.macllvm.whale.model.IProgressCallback;


public class TCPFileSendTask implements Callable<Integer> {
    private static final String TAG = "TCPFileSendTask";
    private SocketChannel socketChannel;
    private FileChannel fileChannel;
    private Selector selector;
    private ByteBuffer byteBuffer;
    private RandomAccessFile randomFile;
    private IProgressCallback progressCallback;
    private volatile boolean isRunning = true;


    public TCPFileSendTask(SocketChannel channel,IProgressCallback callback) {
        socketChannel = channel;
        progressCallback = callback;
        byteBuffer = ByteBuffer.allocate(1024);
        byteBuffer.clear();
    }

    @Override
    public Integer call(){
        try{
            socketChannel.configureBlocking(true);
            socketChannel.socket().setSoTimeout(1000 * 10);
            if(socketChannel.finishConnect()) {
                 String data = "";
                 int len = 0;
                 if((len = socketChannel.read(byteBuffer)) != -1) {
                     byteBuffer.flip();
                     data += new String(byteBuffer.array());
                     byteBuffer.clear();
                 }
                 String[] packets = data.split(":");
                 int fileId = Integer.parseInt(packets[6]);
                 Transfer t = progressCallback.getTransfer(fileId);
                 sendFileData(t);
            }
        }catch(IOException e){
            Log.e(TAG, e.toString());
        }catch(CancellationException e) {
            Log.e(TAG, e.toString());
        } finally {
            try {
                if (null != socketChannel && socketChannel.isOpen())
                    socketChannel.close();
                if (null != fileChannel && fileChannel.isOpen())
                    fileChannel.close();
                if (null != randomFile)
                    randomFile.close();
            }catch(IOException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    private void sendFileData(Transfer transfer) throws IOException {
        if(null != transfer) {
            int readBytes = 0;
            long sendTotal = 0;
            long lastUpdateTime = 0;
            randomFile = new RandomAccessFile(transfer.filePath, "r");
            fileChannel = randomFile.getChannel();
            fileChannel.position(0);
            transfer.state = Transfer.STATE_ONGOING;
            progressCallback.refreshProgress(transfer.index);

            while ( (readBytes = fileChannel.read(byteBuffer) ) != -1) {
                byteBuffer.flip();
                socketChannel.write(byteBuffer);
                byteBuffer.clear();
                sendTotal += readBytes;
                transfer.percent = (int) (sendTotal / (double) transfer.fileSize * 100);

                long now = System.currentTimeMillis();
                if(now - lastUpdateTime > 1000) {
                    lastUpdateTime = now;
                    progressCallback.refreshProgress(transfer.index);
                }
            }

            if (sendTotal == transfer.fileSize) {
                transfer.state = Transfer.STATE_SUCCESS;
            }else{
                transfer.state = Transfer.STATE_FAIL;
            }
        }else{
            transfer.state = Transfer.STATE_FAIL;
        }

        progressCallback.refreshProgress(transfer.index);

    }

}